const {
    app,
    Tray,
    Menu,
    ipcMain,
    MenuItem,
    clipboard,
    BrowserWindow,
    globalShortcut,
} = require("electron");

const fs = require("fs");
const path = require("path");
const { exec } = require("child_process");
const { Search } = require("./src/search");
const { setAutoRun, removeAutoRun } = require("./src/autoRun");

let appIcon;

// 用户设置绑定事件
let setSetting = {
    shortcut: (target, value) => {
        try {
            if (globalShortcut.isRegistered(value)) {
                throw "快捷键设置冲突！";
            }
            else {
                // 移除旧快捷键
                if (target.shortcut != undefined) {
                    globalShortcut.unregister(target.shortcut);
                }
                // 绑定新快捷键
                globalShortcut.register(value, () => {
                    windows.main.webContents.send("init");
                    windows.main[windows.main.isVisible() ? "hide" : "show"]();
                });
                target.shortcut = value;
            }
        }
        catch (err) {
            throw typeof err == "string" ? err : "快捷键设置失败！";
        }
    },
    troyIcon: (target, value) => {
        if (value) {
            appIcon = new Tray(__dirname + "/image/icon/icon.png");
            const contextMenu = Menu.buildFromTemplate([{
                label: "退出",
                click: () => {
                    app.quit();
                }
            }]);

            appIcon.setToolTip("search");
            appIcon.setContextMenu(contextMenu);
            appIcon.on("click", () => {
                windows.main.show();
            });

            // 退出时销毁托盘图标
            quitList.push(appIcon.destroy);
        }
        else {
            if (appIcon) {
                appIcon.destroy();
            }
        }
        target.troyIcon = value;
    },
    openDevTools: (target, value) => {
        target.openDevTools = value;
        windows.main.webContents[value ? "openDevTools" : "closeDevTools"]();
    },
    onTop: (target, value) => {
        target.onTop = value;
        windows.main.setAlwaysOnTop(value);
    },
    autoRun: (target, value) => {
        target.autoRun = value;
        if (value) {
            setAutoRun("search", process.execPath);
        }
        else {
            removeAutoRun("search");
        }
    },
    alias: (target, value) => {
        value.forEach(item => {
            item.path = path.resolve(item.path);
        });
        target.alias = value;
    },
    dirPathList: (target, value) => {
        target.dirPathList = value.map(dirPath => {
            return path.resolve(dirPath);
        });
    },
    setting: (target, value) => {
        // 临时存储require的setting
        target.setting = value;
    }
};

// 用户设置代理
let setting = new Proxy({}, {
    set: (target, key, value) => {
        if (setSetting[key]) {
            if (target[key] != value) {
                setSetting[key](target, value);
            }
        }
        else {
            target[key] = value;
        }
    }
});

// 载入用户设置
setting.setting = require("./setting");

// 保持窗口对象的全局引用，否则窗口会在对象被垃圾回收时自动关闭
let windows = {};

// quit事件执行队列
let quitList = [];

function createMainWindow() {

    // 创建浏览器窗口
    windows.main = new BrowserWindow({
        width: 1000,
        height: 610,

        // 背景透明
        transparent: false,

        // 是否显示边框
        frame: false,

        // 是否可以改变大小
        resizable: false,

        // 开启在任务栏中不显示
        skipTaskbar: false
    });

    // 加载主界面
    windows.main.loadFile(__dirname + "/view/html/index.html");

    // 当window被关闭，这个事件会被触发
    windows.main.on("close", () => {
        delete windows.main;
    });

    // 启动时主界面默认隐藏
    windows.main.hide();

    windows.main.openDevTools();

    windows.main.on("focus", () => {
        windows.main.webContents.send("focus");
    });

    windows.main.on("blur", () => {
        windows.main.webContents.send("blur");
    })

    for (let key in setting.setting) {
        setting[key] = setting.setting[key];
    }
    delete setting.setting;
}

// 设置应用名称
app.setName("search");

// Electron会在初始化后并准备创建浏览器窗口时调用这个函数，部分API在ready事件 触发后才能使用。
app.on("ready", () => {

    createMainWindow();

    // 注册退出事件，清空所有快捷键
    quitList.push(globalShortcut.unregisterAll);
});

app.on("will-quit", () => {
    while (quitList.length != 0) {
        quitList.pop()();
    }
});

// 当全部窗口关闭时触发
app.on("window-all-closed", () => {
    if (process.platform !== "darwin") {
        app.quit();
    }
});

// 关闭窗口
ipcMain.on("close", (event) => {
    if (setting.close == "minimize") {
        // 后台运行
        event.returnValue = windows.main.hide();
    }
    else {
        // 直接退出
        event.returnValue = app.quit();
    }
});

// 获取用户都有哪些设置
ipcMain.on("getSettingKey", (event) => {
    event.returnValue = Object.keys(setting);
});

// 获取用户设置
ipcMain.on("getSetting", (event) => {
    event.returnValue = setting;
});

// 保存用户设置
ipcMain.on("saveSetting", (event, key, value) => {
    try {
        setting[key] = value;
        event.sender.send("saveSetting", key, setting[key], true);
        fs.writeFileSync(__dirname + "/setting.json", JSON.stringify(setting, "pretty-print", 4));
    } catch (err) {
        event.sender.send("saveSetting", key, setting[key], err);
    }
});

// ==================右键菜单 begin=======================
const copy = (content) => {
    clipboard.writeText(content);
};

const menuConfig = {
    copyName: {
        label: "复制文件名",
        click: copy
    },
    copyPath: {
        label: "复制文件路径",
        click: copy
    },
    copyAll: {
        label: "复制完整路径",
        click: copy
    },
    alias: {
        label: "设置别名",
        click: (path) => {
            windows.main.send("setAlias", path);
        }
    }
}

function getMenuConfig(type, content) {
    return {
        label: menuConfig[type].label,
        click: () => {
            menuConfig[type].click(content);
        }
    }
}

ipcMain.on("show-context-menu", (event, menuList) => {
    try {
        const menu = new Menu();
        menuList.forEach(menuItem => {
            menu.append(new MenuItem(getMenuConfig(menuItem.type, menuItem.content)));
        });
        // const win = BrowserWindow.fromWebContents(event.sender);
        menu.popup(windows.main);
    }
    catch (err) {}
});
// ====================右键菜单 end=======================

// 运行应用程序
ipcMain.on("open", (event, file) => {
    file.path = file.path.replace(/<[\s\S]*?>/g, "");
    file.name = file.name.replace(/<[\s\S]*?>/g, "");
    exec(`start "" "${path.join(file.path, file.name)}"`, (err) => {
        if (!err) {
            setTimeout(() => {
                windows.main.hide();
            }, 500);
            event.returnValue = true;
            event.sender.send("open", true);
        }
        else {
            event.sender.send("open", false);
        }
    });
});

// 文件搜索
let search = new Search(setting.setting.dirPathList, {
    dataBase: __dirname + "/search.db"
});

ipcMain.on("keyWord", (event, keyWord) => {
    let option = {
        filter: setting.filter ? new RegExp(`(${ setting.filter.join(")|(") })`) : undefined,
        modifiers: "i"
    };
    search.setDirPathList(setting.dirPathList);
    search.extension(setting.extensions, keyWord, (list) => {
        event.sender.send("keyWord", list, search.consume, search.lastUpdate);
    }, option);
});

ipcMain.on("alias", (event, keyWord) => {
    let list = [];
    let aliasReg = new RegExp(keyWord, "ig");
    setting.alias.filter(item => {
        return keyWord != "" ? aliasReg.test(item.alias) : false;
    }).forEach((item) => {
        if (search.map && search.map[item.path]) {
            let file = Object.assign(search.list[search.map[item.path]]);
            list.push({
                alias: item.alias,
                name: file.name,
                path: file.path
            });
        }
    });
    event.sender.send("alias", list);
});

ipcMain.on("refresh", (event) => {
    search.setDirPathList(setting.dirPathList);
    search.refresh(() => {
        event.sender.send("refresh", search.consume, search.lastUpdate);
    });
});

ipcMain.on("esc", () => {
    windows.main.hide();
});